﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;

namespace Common.MangoDB
{
  /// <summary>
  /// MongoDbHelper,封装与MongoDB数据库的连接、查询、插入、更新和删除等常用操作
  /// </summary>
  public class MongoDbHelper
  {
    /// <summary>
    /// 数据库名称
    /// </summary>
    private string _databaseName = string.Empty;

    /// <summary>
    /// 连接客户端
    /// </summary>
    private readonly IMongoClient _client;

    /// <summary>
    /// 数据库
    /// </summary>
    private IMongoDatabase _database;

    /// <summary>
    /// 初始化MongoDb连接
    /// </summary>
    /// <param name="connectionString"></param>
    public MongoDbHelper(string connectionString)
    {
      _client = new MongoClient(connectionString);
    }

    /// <summary>
    /// 初始化MongoDb连接，指定数据库
    /// </summary>
    /// <param name="connectionString"></param>
    /// <param name="databaseName"></param>
    public MongoDbHelper(string connectionString, string databaseName)
    {
      _client = new MongoClient(connectionString);
      _database = _client.GetDatabase(databaseName);
    }

    /// <summary>
    /// 返回具体数据库
    /// </summary>
    public string DatabaseName
    {
      get => _databaseName;
      set
      {
        _databaseName = value;
        _database = _client.GetDatabase(_databaseName);
      }
    }

    /// <summary>
    /// 执行命令，命令请参考MongoCommand,命令太多，不一一展示，传入的就是里面的字符串，有些命令执行需要连接到admin表
    /// </summary>
    /// <param name="cmdText"></param>
    /// <returns></returns>
    public BsonDocument RunCommand(string cmdText)
    {
      return _database.RunCommand<BsonDocument>(cmdText);
    }

    /// <summary>
    /// 获取当前MongoDB客户端可访问的所有数据库列表。
    /// </summary>
    /// <returns>返回一个包含所有数据库信息的列表。</returns>
    public IList<BsonDocument> GetDatabase()
    {
      // 使用MongoDB客户端的ListDatabases方法获取数据库列表，并将其转换为List集合返回。
      return _client.ListDatabases().ToList();
    }

    /// <summary>
    /// 判断文档存在状态
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public bool IsExistDocument<T>(string documentName, FilterDefinition<T> filter)
    {
      return _database.GetCollection<T>(documentName).Find(filter).Limit(1).Any();
    }

    /// <summary>
    /// 通过条件得到查询的结果个数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public long GetCount<T>(string documentName, FilterDefinition<T> filter)
    {
      return _database.GetCollection<T>(documentName).Find(filter).CountDocuments();
    }

    /// <summary>
    /// 通过系统id(ObjectId)获取一个对象，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public T GetDocumentById<T>(string documentName, string id)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      var result = _database.GetCollection<T>(documentName).Find(filter);
      return result.FirstOrDefault();
    }
    
    /// <summary>
    /// [Async] 通过系统id(ObjectId)获取一个对象，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<T> GetDocumentByIdAsync<T>(string documentName, string id)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      var result = await _database.GetCollection<T>(documentName).FindAsync(filter);
      return await result.FirstOrDefaultAsync();
    }

    /// <summary>
    /// 通过系统id(ObjectId)获取一个对象，id字段可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public T GetDocumentById<T>(string documentName, string idFieldName, string id)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      var result = _database.GetCollection<T>(documentName).Find(filter);
      return result.FirstOrDefault();
    }
    
    /// <summary>
    /// [Async] 通过系统id(ObjectId)获取一个对象，id字段可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<T> GetDocumentByIdAsync<T>(string documentName, string idFieldName, string id)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      var result = await _database.GetCollection<T>(documentName).FindAsync(filter);
      return await result.FirstOrDefaultAsync();
    }

    /// <summary>
    /// 通过系统id(ObjectId)获取一个对象同时过滤字段，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <param name="fields"></param>
    /// <returns></returns>
    public T GetDocumentById<T>(string documentName, string id, ProjectionDefinition<T> fields)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      return _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).FirstOrDefault();
    }

    /// <summary>
    /// 通过系统id(ObjectId)获取一个对象同时过滤字段，id字段可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <param name="fields"></param>
    /// <returns></returns>
    public T GetDocumentById<T>(string documentName, string idFieldName, string id, ProjectionDefinition<T> fields)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      return _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).FirstOrDefault();
    }

    /// <summary>
    /// 通过指定的条件获取一个对象，如果有多条，只取第一条，同时过滤字段
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <param name="fields"></param>
    /// <returns></returns>
    public T GetDocumentByUserFilter<T>(string documentName, FilterDefinition<T> filter, ProjectionDefinition<T> fields)
    {
      return _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).FirstOrDefault();
    }

    /// <summary>
    /// 获取全部文档
    /// </summary>
    /// <typeparam name="T"></typeparam>       
    /// <param name="documentName"></param>
    /// <returns></returns>
    public IList<T> GetAllDocuments<T>(string documentName)
    {
      var filter = Builders<T>.Filter.Empty;
      return _database.GetCollection<T>(documentName).Find(filter).ToList();
    }
    
    /// <summary>
    /// [Async] 获取全部文档
    /// </summary>
    /// <typeparam name="T"></typeparam>       
    /// <param name="documentName"></param>
    /// <returns></returns>
    public async Task<IList<T>> GetAllDocumentsAsync<T>(string documentName)
    {
      var filter = Builders<T>.Filter.Empty;
      var result = await _database.GetCollection<T>(documentName).FindAsync(filter);
      return await result.ToListAsync();
    }

    /// <summary>
    /// 获取全部文档同时过滤字段
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="fields">要获取的字段</param>
    /// <returns></returns>
    public IList<T> GetAllDocuments<T>(string documentName, ProjectionDefinition<T> fields)
    {
      var filter = Builders<T>.Filter.Empty;
      return _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).ToList();
    }

    /// <summary>
    /// 通过一个条件获取对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="property">字段名</param>
    /// <param name="value">字段值</param>
    /// <returns></returns>
    public IList<T> GetDocumentsByFilter<T>(string documentName, string property, string value)
    {
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      return _database.GetCollection<T>(documentName).Find(filter).ToList();
    }
    
    /// <summary>
    /// [Async] 通过一个条件获取对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="property">字段名</param>
    /// <param name="value">字段值</param>
    /// <returns></returns>
    public async Task<IList<T>> GetDocumentsByFilterAsync<T>(string documentName, string property, string value)
    {
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      var result = await _database.GetCollection<T>(documentName).FindAsync(filter);
      return await result.ToListAsync();
    }

    /// <summary>
    /// 通过条件获取对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public IList<T> GetDocumentsByFilter<T>(string documentName, FilterDefinition<T> filter)
    {
      return _database.GetCollection<T>(documentName).Find(filter).ToList();
    }
    
    /// <summary>
    /// [Async] 通过条件获取对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public async Task<IList<T>> GetDocumentsByFilterAsync<T>(string documentName, FilterDefinition<T> filter)
    {
      var result = await _database.GetCollection<T>(documentName).FindAsync(filter);
      return await result.ToListAsync();
    }

    /// <summary>
    /// 通过条件获取对象,同时过滤字段
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="property">字段名</param>
    /// <param name="value">字段值</param>
    /// <param name="fields">要获取的字段</param>
    /// <returns></returns>
    public IList<T> GetDocumentsByFilter<T>(string documentName, string property, string value,
      ProjectionDefinition<T> fields)
    {
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      return _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).ToList();
    }

    /// <summary>
    /// 通过条件获取对象,同时过滤数据和字段
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter">过滤器</param>
    /// <param name="fields">要获取的字段</param>
    /// <returns></returns>
    public IList<T> GetDocumentsByFilter<T>(string documentName, FilterDefinition<T> filter,
      ProjectionDefinition<T> fields)
    {
      return _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).ToList();
    }

    /// <summary>
    /// 通过条件获取分页的文档并排序
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <param name="fields"></param>
    /// <param name="sort"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <returns></returns>
    public IList<T> GetPagedDocumentsByFilter<T>(string documentName, FilterDefinition<T> filter,
      ProjectionDefinition<T> fields, SortDefinition<T> sort, int pageIndex, int pageSize)
    {
      IList<T> result;
      if (pageIndex != 0 && pageSize != 0)
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).Sort(sort)
          .Skip(pageSize * (pageIndex - 1)).Limit(pageSize).ToList();
      }
      else
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Project<T>(fields).Sort(sort).ToList();
      }

      return result;
    }

    /// <summary>
    /// 通过条件获取分页的文档并排序
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <param name="sort"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <returns></returns>
    public IList<T> GetPagedDocumentsByFilter<T>(string documentName, FilterDefinition<T> filter,
      SortDefinition<T> sort, int pageIndex, int pageSize)
    {
      IList<T> result;
      if (pageIndex != 0 && pageSize != 0)
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Sort(sort).Skip(pageSize * (pageIndex - 1))
          .Limit(pageSize).ToList();
      }
      else
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Sort(sort).ToList();
      }

      return result;
    }

    /// <summary>
    /// 通过条件获取分页的文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <returns></returns>
    public IList<T> GetPagedDocumentsByFilter<T>(string documentName, FilterDefinition<T> filter, int pageIndex,
      int pageSize)
    {
      IList<T> result;
      if (pageIndex != 0 && pageSize != 0)
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Skip(pageSize * (pageIndex - 1)).Limit(pageSize)
          .ToList();
      }
      else
      {
        result = _database.GetCollection<T>(documentName).Find(filter).ToList();
      }

      return result;
    }

    /// <summary>
    /// 获取分页的文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="sort"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <returns></returns>
    public IList<T> GetPagedDocumentsByFilter<T>(string documentName, SortDefinition<T> sort, int pageIndex,
      int pageSize)
    {
      IList<T> result;
      var filter = Builders<T>.Filter.Empty;
      if (pageIndex != 0 && pageSize != 0)
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Sort(sort).Skip(pageSize * (pageIndex - 1))
          .Limit(pageSize).ToList();
      }
      else
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Sort(sort).ToList();
      }

      return result;
    }

    /// <summary>
    /// 获取分页的文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <returns></returns>
    public IList<T> GetPagedDocumentsByFilter<T>(string documentName, int pageIndex, int pageSize)
    {
      IList<T> result;
      var filter = Builders<T>.Filter.Empty;
      if (pageIndex != 0 && pageSize != 0)
      {
        result = _database.GetCollection<T>(documentName).Find(filter).Skip(pageSize * (pageIndex - 1)).Limit(pageSize)
          .ToList();
      }
      else
      {
        result = _database.GetCollection<T>(documentName).Find(filter).ToList();
      }

      return result;
    }

    /// <summary>
    /// 新增
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="document"></param>
    /// <returns></returns>
    public void Insert<T>(string documentName, T document)
    {
      try
      {
        _database.GetCollection<T>(documentName).InsertOne(document);
      }
      catch (MongoWriteException me)
      {
        MongoBulkWriteException mbe = me.InnerException as MongoBulkWriteException;
        if (mbe != null && mbe.HResult == -2146233088)
          throw new Exception("Insert duplicate keys!");
        if (mbe != null) throw new Exception(mbe.Message);
      }
    }
    
    /// <summary>
    /// [Async] 新增
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="document"></param>
    /// <returns></returns>
    public async Task InsertAsync<T>(string documentName, T document)
    {
      try
      {
        await _database.GetCollection<T>(documentName).InsertOneAsync(document);
      }
      catch (MongoWriteException me)
      {
        MongoBulkWriteException mbe = me.InnerException as MongoBulkWriteException;
        if (mbe != null && mbe.HResult == -2146233088)
          throw new Exception("Insert duplicate keys!");
        if (mbe != null) throw new Exception(mbe.Message);
      }
    }

    /// <summary>
    /// 新增多个文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="documents"></param>
    /// <returns></returns>
    public void InsertMany<T>(string documentName, IList<T> documents)
    {
      try
      {
        _database.GetCollection<T>(documentName).InsertMany(documents);
      }
      catch (MongoWriteException me)
      {
        MongoBulkWriteException mbe = me.InnerException as MongoBulkWriteException;
        if (mbe != null && mbe.HResult == -2146233088)
          throw new Exception("Insert duplicate keys!");
        if (mbe != null) throw new Exception(mbe.Message);
      }
    }
    
    /// <summary>
    /// [Async] 新增多个文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="documents"></param>
    /// <returns></returns>
    public async Task InsertManyAsync<T>(string documentName, IList<T> documents)
    {
      try
      {
        await _database.GetCollection<T>(documentName).InsertManyAsync(documents);
      }
      catch (MongoWriteException me)
      {
        MongoBulkWriteException mbe = me.InnerException as MongoBulkWriteException;
        if (mbe != null && mbe.HResult == -2146233088)
          throw new Exception("Insert duplicate keys!");
        if (mbe != null) throw new Exception(mbe.Message);
      }
    }

    /// <summary>
    /// 修改，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <param name="oldInfo"></param>
    /// <returns></returns>
    public void UpdateReplaceOne<T>(string documentName, string id, T oldInfo)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      _database.GetCollection<T>(documentName).ReplaceOne(filter, oldInfo);
    }
    
    /// <summary>
    /// [Async] 修改，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <param name="oldInfo"></param>
    /// <returns></returns>
    public async Task UpdateReplaceOneAsync<T>(string documentName, string id, T oldInfo)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      await _database.GetCollection<T>(documentName).ReplaceOneAsync(filter, oldInfo);
    }

    /// <summary>
    /// 修改，id字段名称可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <param name="oldInfo"></param>
    /// <returns></returns>
    public void UpdateReplaceOne<T>(string documentName, string idFieldName, string id, T oldInfo)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      _database.GetCollection<T>(documentName).ReplaceOne(filter, oldInfo);
    }
    
    /// <summary>
    /// [Async] 修改，id字段名称可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <param name="oldInfo"></param>
    /// <returns></returns>
    public async Task UpdateReplaceOneAsync<T>(string documentName, string idFieldName, string id, T oldInfo)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      await _database.GetCollection<T>(documentName).ReplaceOneAsync(filter, oldInfo);
    }

    /// <summary>
    /// 只能替换一条，如果有多条的话
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <param name="oldInfo"></param>
    public void UpdateReplaceOne<T>(string documentName, FilterDefinition<T> filter, T oldInfo)
    {
      _database.GetCollection<T>(documentName).ReplaceOne(filter, oldInfo);
    }
    
    /// <summary>
    /// [Async] 只能替换一条，如果有多条的话
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <param name="oldInfo"></param>
    public async Task UpdateReplaceOneAsync<T>(string documentName, FilterDefinition<T> filter, T oldInfo)
    {
      await _database.GetCollection<T>(documentName).ReplaceOneAsync(filter, oldInfo);
    }

    /// <summary>
    /// 更新指定属性值，按ID就只有一条，替换一条，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <param name="property"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public void Update<T>(string documentName, string id, string property, string value)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      var update = Builders<T>.Update.Set(property, value);
      _database.GetCollection<T>(documentName).UpdateOne(filter, update);
    }
    
    /// <summary>
    /// [Async] 更新指定属性值，按ID就只有一条，替换一条，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <param name="property"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public async Task UpdateAsync<T>(string documentName, string id, string property, string value)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq("_id", oid);
      var update = Builders<T>.Update.Set(property, value);
      await _database.GetCollection<T>(documentName).UpdateOneAsync(filter, update);
    }

    /// <summary>
    /// 更新指定属性值，按ID就只有一条，替换一条，id字段名称可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <param name="property"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public void Update<T>(string documentName, string idFieldName, string id, string property, string value)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      var update = Builders<T>.Update.Set(property, value);
      _database.GetCollection<T>(documentName).UpdateOne(filter, update);
    }
    
    /// <summary>
    /// [Async] 更新指定属性值，按ID就只有一条，替换一条，id字段名称可以自定义
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="idFieldName"></param>
    /// <param name="id"></param>
    /// <param name="property"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public async Task UpdateAsync<T>(string documentName, string idFieldName, string id, string property, string value)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filter = Builders<T>.Filter.Eq(idFieldName, oid);
      var update = Builders<T>.Update.Set(property, value);
      await _database.GetCollection<T>(documentName).UpdateOneAsync(filter, update);
    }

    /// <summary>
    /// 更新指定文档集合中的单个文档。
    /// </summary>
    /// <typeparam name="T">文档的类型。</typeparam>
    /// <param name="documentName">文档集合的名称。</param>
    /// <param name="filter">用于标识要更新的文档的过滤条件。</param>
    /// <param name="update">要应用的更新操作。</param>
    public void Update<T>(string documentName, FilterDefinition<T> filter, UpdateDefinition<T> update)
    {
      // 获取指定名称的文档集合，并执行更新操作
      _database.GetCollection<T>(documentName).UpdateOne(filter, update);
    }
    
    /// <summary>
    /// 更新指定文档集合中的单个文档。
    /// </summary>
    /// <typeparam name="T">文档的类型。</typeparam>
    /// <param name="documentName">文档集合的名称。</param>
    /// <param name="filter">用于标识要更新的文档的过滤条件。</param>
    /// <param name="update">要应用的更新操作。</param>
    public async Task UpdateAsync<T>(string documentName, FilterDefinition<T> filter, UpdateDefinition<T> update)
    {
      // 获取指定名称的文档集合，并执行更新操作
      await _database.GetCollection<T>(documentName).UpdateOneAsync(filter, update);
    }

    /// <summary>
    /// 更新集合中符合条件的文档。
    /// </summary>
    /// <typeparam name="T">集合中文档的类型。</typeparam>
    /// <param name="documentName">集合的名称。</param>
    /// <param name="filter">用于筛选文档的过滤条件。</param>
    /// <param name="update">要执行的更新操作。</param>
    public void UpdateMany<T>(string documentName, FilterDefinition<T> filter, UpdateDefinition<T> update)
    {
      // 获取指定名称的集合，并执行批量更新操作。
      _database.GetCollection<T>(documentName).UpdateMany(filter, update);
    }
    
    /// <summary>
    /// 更新集合中符合条件的文档。
    /// </summary>
    /// <typeparam name="T">集合中文档的类型。</typeparam>
    /// <param name="documentName">集合的名称。</param>
    /// <param name="filter">用于筛选文档的过滤条件。</param>
    /// <param name="update">要执行的更新操作。</param>
    public async Task UpdateManyAsync<T>(string documentName, FilterDefinition<T> filter, UpdateDefinition<T> update)
    {
      // 获取指定名称的集合，并执行批量更新操作。
      await _database.GetCollection<T>(documentName).UpdateManyAsync(filter, update);
    }

    /// <summary>
    /// 删除一个文档，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public void Delete<T>(string documentName, string id)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filterId = Builders<T>.Filter.Eq("_id", oid);
      _database.GetCollection<T>(documentName).DeleteOne(filterId);
    }
    
    /// <summary>
    /// 删除一个文档，id字段是[_id]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task DeleteAsync<T>(string documentName, string id)
    {
      ObjectId oid = ObjectId.Parse(id);
      var filterId = Builders<T>.Filter.Eq("_id", oid);
      await _database.GetCollection<T>(documentName).DeleteOneAsync(filterId);
    }

    /// <summary>
    /// 从指定集合中删除符合特定条件的文档。id字段名称可以自定义
    /// </summary>
    /// <typeparam name="T">集合中文档的类型。</typeparam>
    /// <param name="documentName">集合的名称。</param>
    /// <param name="property">用于筛选文档的属性名称。</param>
    /// <param name="value">属性应匹配的值。</param>
    public void Delete<T>(string documentName, string property, string value)
    {
      // 创建一个过滤器，用于查找属性值匹配指定条件的文档。
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      
      // 从数据库中获取指定名称的集合，并根据过滤器删除一个文档。
      _database.GetCollection<T>(documentName).DeleteOne(filter);
    }
    
    /// <summary>
    /// 从指定集合中删除符合特定条件的文档。id字段名称可以自定义
    /// </summary>
    /// <typeparam name="T">集合中文档的类型。</typeparam>
    /// <param name="documentName">集合的名称。</param>
    /// <param name="property">用于筛选文档的属性名称。</param>
    /// <param name="value">属性应匹配的值。</param>
    public async Task DeleteAsync<T>(string documentName, string property, string value)
    {
      // 创建一个过滤器，用于查找属性值匹配指定条件的文档。
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      
      // 从数据库中获取指定名称的集合，并根据过滤器删除一个文档。
      await _database.GetCollection<T>(documentName).DeleteOneAsync(filter);
    }

    /// <summary>
    /// 通过一个属性名和属性值删除多个文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="property"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public void DeleteMany<T>(string documentName, string property, string value)
    {
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      _database.GetCollection<T>(documentName).DeleteMany(filter);
    }
    
    /// <summary>
    /// 通过一个属性名和属性值删除多个文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="property"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public async Task DeleteManyAsync<T>(string documentName, string property, string value)
    {
      FilterDefinition<T> filter = Builders<T>.Filter.Eq(property, value);
      await _database.GetCollection<T>(documentName).DeleteManyAsync(filter);
    }

    /// <summary>
    /// 通过一个属性名和属性值删除多个文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public void DeleteMany<T>(string documentName, FilterDefinition<T> filter)
    {
      _database.GetCollection<T>(documentName).DeleteMany(filter);
    }
    
    /// <summary>
    /// 通过一个属性名和属性值删除多个文档
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="documentName"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    public async Task DeleteManyAsync<T>(string documentName, FilterDefinition<T> filter)
    {
      await _database.GetCollection<T>(documentName).DeleteManyAsync(filter);
    }

    /// <summary>
    /// 有些命令要求你连到系统库上才能执行
    /// You need to link to the admin table if you want to run system command;eg:listDatabases ,the following url show you the details
    /// https://docs.mongodb.com/manual/reference/command/listCommands/
    /// </summary>
    public sealed class MongoCommand
    {
      /// <summary>
      /// ListDatabases
      /// </summary>
      public const string ListDatabases = "{listDatabases:1}";
      
      /// <summary>
      /// ListCommands
      /// </summary>
      public const string ListCommands = "{listCommands:1}";
    }
  }
}